package com.dferreira.languagesteach.activities;

import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ViewFlipper;

import com.dferreira.languagesteach.R;
import com.dferreira.languagesteach.activities.generic.ExercisesActivity;
import com.dferreira.languagesteach.constants.Constants;
import com.dferreira.languagesteach.data_adapters.WorkoutAdapter;
import com.dferreira.languagesteach.helpers.GenericUI;
import com.dferreira.languagesteach.helpers.IntroductionDelegator;
import com.dferreira.languagesteach.meta_data.IntroductionState;
import com.dferreira.languagesteach.utils.GesturesHandlerInterface;
import com.dferreira.languagesteach.utils.SwipeDetector;

/**
 * Introduction activity On this screen image pass and
 * visual and audio descriptions are provided
 *
 * @author dferreira
 */
public class IntroductionActivity extends ExercisesActivity implements
        OnClickListener, GesturesHandlerInterface {

    private GestureDetector gestureDetector;

    private IntroductionState introductionState;


    private WorkoutAdapter workoutAdapter;
    private IntroductionDelegator introductionDelegator;
    private Boolean dataSetBuilt;

    /**
     * Called when controller is created. Associate buttons to variables Set his
     * delegator. Register event listeners Hide the controller menu Set power to
     * not dim canvas
     *
     * @param savedInstanceState If the activity is being re-initialized after
     *                           previously being shut down then this Bundle contains the data it most
     *                           recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {


        String packageFolderKey;
        Integer waitBeforeNextSlide;
        String packageFolder;

        /*UI elements*/
        ViewFlipper viewFlipper;
        TextView imageDescription1;
        TextView imageDescription2;
        LinearLayout playerPanel;
        TextView imageCounter;
        ImageButton againBtn, backBtn, playAndPauseBtn, nextBtn, stopBtn;
        Bundle intentExtras;

        /*Logical implementation*/
        super.onCreate(savedInstanceState);
        setContentView(R.layout.introduction);

        packageFolderKey = Constants.PACKAGE_FOLDER_KEY;

        intentExtras = getIntent().getExtras();
        if (intentExtras != null) {
            packageFolder = intentExtras.getString(packageFolderKey);
        } else {
            packageFolder = null;
        }


		/* Get all view controllers */
        viewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);
        imageDescription1 = (TextView) findViewById(R.id.imageDescription1);
        imageDescription2 = (TextView) findViewById(R.id.imageDescription2);
        imageCounter = (TextView) findViewById(R.id.imageCounter);
        playerPanel = (LinearLayout) findViewById(R.id.playerPanel);
        againBtn = (ImageButton) findViewById(R.id.againBtn);
        backBtn = (ImageButton) findViewById(R.id.backBtn);
        playAndPauseBtn = (ImageButton) findViewById(R.id.playAndPauseBtn);
        nextBtn = (ImageButton) findViewById(R.id.nextBtn);
        stopBtn = (ImageButton) findViewById(R.id.stopBtn);


		/* Get data models */
        workoutAdapter = new WorkoutAdapter(this, packageFolder);
        dataSetBuilt = workoutAdapter.buildDataSet();
        if (dataSetBuilt) {
            waitBeforeNextSlide = Constants.WAIT_BEFORE_NEXT_SLIDE;

            introductionDelegator = new IntroductionDelegator(this,
                    viewFlipper, imageDescription1, imageDescription2,
                    imageCounter, playerPanel,
                    againBtn, backBtn, playAndPauseBtn, nextBtn, this,
                    workoutAdapter, waitBeforeNextSlide);

			/* Configure buttons listeners */
            againBtn.setOnClickListener(this);
            backBtn.setOnClickListener(this);
            playAndPauseBtn.setOnClickListener(this);
            nextBtn.setOnClickListener(this);
            stopBtn.setOnClickListener(this);
            //noinspection deprecation
            gestureDetector = new GestureDetector(new SwipeDetector(this));
            playerPanel.setVisibility(View.GONE);


        } else {
            super.onBackPressed();
        }

    }


    /**
     * Called when activity is putted on.
     * Set the lock to human concurrent human
     * interaction.
     * Call resume from introduction delegate
     */
    @Override
    public void onResume() {
        String currentStateKey;
        Bundle intentExtras;

        super.onResume();
        if (!dataSetBuilt) {
            finish();
            return;
        }
        /* Avoid lose lightness from display */
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        currentStateKey = Constants.CURRENT_STATE_KEY;
        intentExtras = getIntent().getExtras();
        if (intentExtras != null) {
            introductionState = (IntroductionState) intentExtras.get(
                    currentStateKey);
        }
        if (introductionState == null) {
            introductionState = new IntroductionState();
        }
        introductionDelegator.onResume(introductionState);
    }

    /**
     * On pause save the concurrent human interaction lock Call the pause method
     * from introduction delegate
     */
    @Override
    public void onPause() {
        String currentStateKey;

        super.onPause();
        if (!dataSetBuilt) {
            return;
        }
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        currentStateKey = Constants.CURRENT_STATE_KEY;
        getIntent().putExtra(currentStateKey, introductionState);
        introductionDelegator.onPause();
    }

    /**
     * Called when is to finish the activity
     */
    @Override
    public void finish() {
        if (workoutAdapter.wasNotDataSetBuilt()
                || introductionDelegator.getWithErrors()) {
            setResult(GenericUI.RESULT_CORRUPTED_PACKAGE, null);
        }
        super.finish();
    }

    /**
     * Directs the click at one from a button to a specific method on
     * introduction delegate
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.againBtn: {
                introductionDelegator.reload();
                break;
            }
            case R.id.backBtn: {
                // Back
                introductionDelegator.previous();
                break;
            }
            case R.id.playAndPauseBtn: {
                introductionDelegator.playAndPause();
                break;
            }
            case R.id.nextBtn: {
                introductionDelegator.forward();
                break;
            }
            case R.id.stopBtn: {
                // Stop
                introductionDelegator.stop();
                break;
            }
            default:
                break;
        }

    }

    /**
     * Directs a touch event to a gesture detector instantiated
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event);
    }

    /**
     * Treat user's motion when user draws the view to left calling the introduction delegate
     */
    @Override
    public void dragToLeft() {
        introductionDelegator.forward();
    }

    /**
     * Treat user's motion when user draws the view to right calling the introduction delegate
     */
    @Override
    public void dragToRight() {
        introductionDelegator.previous();
    }

    /**
     * Treat user's motion when user draws the view to up calling the introduction delegate
     */
    @Override
    public void dragUp() {
        introductionDelegator.stop();
    }

    /**
     * Treat user's motion when user draws the view to down calling the introduction delegate
     */
    @Override
    public void dragDown() {
        // DO nothing
    }

    /**
     * Treat user's action when user makes a single tap
     */
    @Override
    public void singleTap() {
        introductionDelegator.showAndHidePlayerMenu();
    }

    /**
     * Treat user's action when user makes a double tap
     */
    @Override
    public void doubleTap() {
        introductionDelegator.playAndPause();
    }
}
